package com.maiji.cloud.listener;

import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.maiji.cloud.entities.shopingmall.*;
import com.maiji.cloud.service.*;
import com.maiji.cloud.service.impl.ShopingOrderServiceImpl;
import com.maiji.cloud.utils.Arith;
import com.maiji.cloud.utils.CommonIntValueEnum;
import com.maiji.cloud.utils.Express100Util;
import com.maiji.cloud.utils.FlowTypeEnum;
import net.sf.json.JSONObject;
import org.apache.commons.lang.BooleanUtils;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.time.LocalDate;
import java.time.ZoneId;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.stream.Collectors;

@Service
@Transactional
public class ScheduledService {

    private Logger logger = LoggerFactory.getLogger(ShopingOrderServiceImpl.class);
    @Autowired
    private ShipmentsInfoService shipmentsInfoService;
    @Autowired
    private ShopingOrderService shopingOrderService;
    @Autowired
    private CapitalMainService capitalMainService;
    @Autowired
    private ShareOrderHelpLogService shareOrderHelpLogService;
    @Autowired
    private ShareOrderLogService shareOrderLogService;
    @Autowired
    private ShopingOrderRefundService shopingOrderRefundService;
    @Autowired
    private MongoTemplate mongoTemplate;

    // 统计订单返现分享助力总金额
    @Scheduled(cron = "${cron.statisticShareOrderHelp}") // 每30分钟执行一次
    public void statisticShareOrderHelp() {
        EntityWrapper<ShareOrderLog> entityWrapper = new EntityWrapper<>();
        entityWrapper.eq("settlement", false);
        entityWrapper.eq("termination", false);
        entityWrapper.le("end_time", new Date());
        entityWrapper.orderBy("end_time", true);
        List<ShareOrderLog> shareOrderLogs = shareOrderLogService.selectList(entityWrapper);
        for (ShareOrderLog shareOrderLog: shareOrderLogs) {
            EntityWrapper<ShareOrderHelpLog> entityWrapper1 = new EntityWrapper<>();
            entityWrapper1.eq("share_order_log_id", shareOrderLog.getUuId());
            Double totalHelpMoney = shareOrderHelpLogService.selectList(entityWrapper1)
                    .stream().map(ShareOrderHelpLog::getHelpMoney).reduce(Double.valueOf(0), (hm1, hm2) -> Arith.add(2, hm1, hm2));
            if (! shareOrderLogService.updateById(shareOrderLog.setReturMoney(totalHelpMoney).setSettlement(true))) {
                logger.info("统计订单返现分享助力总金额 ===>> 订单分享ID={} ===>> 修改订单返现活动记录的结算状态：失败", new Object[]{shareOrderLog.getUuId()});
                continue;
            }
            if (! capitalMainService.updateCapitalMain(shareOrderLog.getUserId(), FlowTypeEnum.RETURNMONEY, totalHelpMoney.toString(),
                    FlowTypeEnum.INCREASE, FlowTypeEnum.SHAREORDERHELP, shareOrderLog.getUuId())) {
                logger.info("统计订单返现分享助力总金额 ===>> 订单分享ID={} ===>> 将订单返现加入到用户资金账户：失败 ===>> 用户ID={} ===>> 助力总金额={}元",
                        new Object[]{shareOrderLog.getUuId(), shareOrderLog.getUserId(), totalHelpMoney});
                continue;
            }
            ShopingOrder shopingOrder = new ShopingOrder()
                    .setUuId(shareOrderLog.getOrderId())
                    .setShareOrder(true)
                    .setShareOrderMoney(totalHelpMoney);
            if (! shopingOrderService.updateById(shopingOrder)) {
                logger.info("统计订单返现分享助力总金额 ===>> 订单分享ID={} ===>> 修改订单的订单返现状态：失败 ===>> 订单ID={}",
                        new Object[]{shareOrderLog.getUuId(), shopingOrder.getUuId()});
                continue;
            }
            logger.info("统计订单返现分享助力总金额 ===>> 订单分享ID={} ===>> {}", new Object[]{shareOrderLog.getUuId(), "成功"});
        }
    }

    // 定时删除发货信息的base64数据
    @Scheduled(cron = "${cron.deleteBase64}")
    public void deleteBase64() {
        LocalDate today = LocalDate.now();
        LocalDate yesterday = today.plusDays(1);
        EntityWrapper<ShipmentsInfoEntity> entityWrapper = new EntityWrapper<>();
        entityWrapper.le("send_date", yesterday);
        List<ShipmentsInfoEntity> shipmentsInfoEntities = shipmentsInfoService.selectList(entityWrapper).stream()
                .map(sInfo -> sInfo.setImgBase64("")).collect(Collectors.toList());
        boolean updateBatch = shipmentsInfoService.updateBatchById(shipmentsInfoEntities);
        logger.info("定时删除发货信息的base64数据 ===>> {}", updateBatch);
    }

    // 定时自动收货
    @Scheduled(cron = "${cron.shopingOrderAutoReceive}")
    public void shopingOrderAutoReceive() {
        HashMap orderAutoSetMap = mongoTemplate.findOne(new Query(), HashMap.class, "order_auto_set");
        Integer autoReceive = Integer.valueOf(orderAutoSetMap.get("auto_receive").toString());
        EntityWrapper<ShopingOrder> entityWrapper = new EntityWrapper<>();
        entityWrapper.eq("refund_status", -1);
        entityWrapper.eq("status", 2);
        entityWrapper.isNotNull("send_date");
        List<ShopingOrder> shopingOrders = shopingOrderService.selectList(entityWrapper);
        List<ShopingOrder> receivedOrders = shopingOrders.parallelStream().map(shopingOrder -> {
            LocalDate sendDate = shopingOrder.getSendDate().toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
            LocalDate autoReceiveDate = sendDate.plusDays(autoReceive);
            if (LocalDate.now().isBefore(autoReceiveDate)) return shopingOrder;
            return shopingOrder.setStatus(3).setAutoReceive(true).setReceiveDate(new Date());
        }).filter(ShopingOrder::getAutoReceive).collect(Collectors.toList());
        if (receivedOrders.size() > 0) {
            List<ShipmentsInfoEntity> shipmentsInfos = shipmentsInfoService.selectList(new EntityWrapper<ShipmentsInfoEntity>()
                    .in("order_id", receivedOrders.parallelStream().map(ShopingOrder::getUuId).collect(Collectors.toList())));
            List<String> orderIds = shipmentsInfos.stream().filter(si -> {
                JSONObject jsonObject = JSONObject.fromObject(Express100Util.expressQuery(si.getCompanyCode(),
                        si.getExpressNo(), null, null, null, 0));
                Object ischeck = jsonObject.get("ischeck");
                if (ischeck == null) return true;
                else return Integer.valueOf(ischeck.toString()) == 1;
            }).map(ShipmentsInfoEntity::getOrderId).collect(Collectors.toList());
            receivedOrders = receivedOrders.parallelStream().filter(order -> orderIds.contains(order.getUuId())).collect(Collectors.toList());
            if (receivedOrders.size() > 0 && shopingOrderService.updateBatchById(receivedOrders)) {
                String orderNos = orderIds.parallelStream().collect(Collectors.joining(","));
                logger.info("订单发货 {} 天后自动确认收货成功 ===>> OrderNos=[{}]", autoReceive, orderNos);
            }
        }
    }

    // 定时完成订单
    @Scheduled(cron = "${cron.shopingOrderAutoDone}")
    public void shopingOrderAutoDone() {
        EntityWrapper<ShopingOrder> entityWrapper = new EntityWrapper<>();
        entityWrapper.eq("refund_status", -1);
        entityWrapper.in("status", Arrays.asList(3, 5));
        List<ShopingOrder> shopingOrders = shopingOrderService.selectList(entityWrapper);
        List<ShopingOrder> receivedShopingOrders = shopingOrders.stream().map(shopingOrder -> {
            LocalDate receiveDate = shopingOrder.getReceiveDate().toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
            LocalDate autoDoneDate = receiveDate.plusDays(7);
            if (LocalDate.now().isBefore(autoDoneDate)) return shopingOrder;
            // 解冻该订单产生的分销佣金 // 不用 parallelStream 防止出现并发问题
            if (BooleanUtils.isTrue(shopingOrder.getCommission())) capitalMainService.unfreezeDistributionMoney(shopingOrder.getUuId());
            return shopingOrder.setStatus(6).setDoneDate(new Date());
        }).collect(Collectors.toList());
        if (receivedShopingOrders.size() > 0 && shopingOrderService.updateBatchById(receivedShopingOrders)) {
            String orderNos = StringUtils.join(receivedShopingOrders.stream().map(ShopingOrder::getOrderNo).collect(Collectors.toList()), ",");
            logger.info("确认收货7天后自动完成订单成功 ===>> OrderNos=[{}]", orderNos);
        }
    }

    // 申请退款审核拒绝后定时撤销
    @Scheduled(cron = "${cron.ShoppingOrderRefundAutoCancel}")
    public void ShoppingOrderRefundAutoCancel() {
        EntityWrapper<ShoppingOrderRefundEntity> entityWrapper = new EntityWrapper<>();
        entityWrapper.eq("status", CommonIntValueEnum.SHOPPING_ORDER_REFUND_STATUS_REFUND_REFUSE.getValue());
        List<ShoppingOrderRefundEntity> shoppingOrderRefunds = shopingOrderRefundService.selectList(entityWrapper);
        StringBuffer orderIds = new StringBuffer();
        List<ShoppingOrderRefundEntity> cancelShoppingOrderRefunds = shoppingOrderRefunds.parallelStream().filter(shoppingOrderRefund -> {
            LocalDate stayRefundTime = shoppingOrderRefund.getStayRefundTime().toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
            LocalDate autoCancelDate = stayRefundTime.plusDays(3);
            if (LocalDate.now().isBefore(autoCancelDate)) return false;
            orderIds.append(shoppingOrderRefund.getOrderId() + ", ");
            shoppingOrderRefund.setRefundCancelTime(new Date())
                    .setStatus(CommonIntValueEnum.SHOPPING_ORDER_REFUND_NONE.getValue());
            return true;
        }).collect(Collectors.toList());
        if (cancelShoppingOrderRefunds.size() > 0 && shopingOrderRefundService.updateBatchById(cancelShoppingOrderRefunds))
            logger.info("退款申请审核拒绝后3天自动撤销退款 ===>> OrderIds=[{}]", orderIds);
    }

}
